package la.iok.hzsvn.lewin.movie.service;

import la.iok.hzsvn.lewin.movie.config.DfsProperties;
import la.iok.hzsvn.lewin.movie.core.RoleEnum;
import la.iok.hzsvn.lewin.movie.core.Token;
import la.iok.hzsvn.lewin.movie.core.exception.ErrorCode;
import la.iok.hzsvn.lewin.movie.core.model.UserVo;
import la.iok.hzsvn.lewin.movie.entity.UserFile;
import la.iok.hzsvn.lewin.movie.services.MovieServiceInvoker;
import la.iok.hzsvn.lewin.mybatis.service.BaseServiceImpl;
import la.iok.hzsvn.lewin.movie.mapper.UserFileMapper;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.annotations.Nullable;
import la.iok.hzsvn.share.dfs.exception.DfsException;
import la.iok.hzsvn.share.tools.crypto.Sha1Util;
import la.iok.hzsvn.share.tools.exception.SystemException;
import la.iok.hzsvn.share.utils.ParameterTypeUtils;
import la.iok.hzsvn.share.utils.PathUtils;
import la.iok.hzsvn.share.utils.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import la.iok.hzsvn.share.dfs.model.DfsDescriptor;
import la.iok.hzsvn.share.dfs.model.DfsResult;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import la.iok.hzsvn.lewin.movie.service.UserFileService;

@Service
public class UserFileServicelmpl extends BaseServiceImpl<UserFile,UserFileMapper,Long> implements UserFileService
{
    private final MovieServiceInvoker movieServiceInvoker;
    protected final WebDfsService webDfsService;
    private final DfsProperties dfsProperties;
    public UserFileServicelmpl(UserFileMapper mapper,
                               MovieServiceInvoker movieServiceInvoker,
                               WebDfsService webDfsService,
                               DfsProperties dfsProperties) {

        super(mapper);
        this.mapper=mapper;
        this.movieServiceInvoker = movieServiceInvoker;
        this.webDfsService = webDfsService;
        this.dfsProperties = dfsProperties;
    }

    public void uploadCover(@NotNull Token token, @Nullable Long userId, @NotNull MultipartFile file, String path)
    {
        if(token.getUserId()!=userId)
        {
            System.out.println("tokenID！=userId");
            ErrorCode.AUTHORITY_ERROR.assertTrue(token.hasAnyAuthority(RoleEnum.Admin,RoleEnum.Manager, RoleEnum.ShopManager));
        }
        UserVo uservo=movieServiceInvoker.userInfo(userId);
        ErrorCode.ROLE_NOT_EXIST.assertNotNull(uservo);
        if(!(uservo == null)) {
            Long id = uploadFile(file,userId);
            System.out.println("File="+file+"UserId="+userId+"Path="+path);
            mapper.updateUserCoverData(userId,id,path);
        }
    }

    public File transToLocalFile(@NotNull MultipartFile file) {
        // 1、把上传的文件写到本地临时文件
        String ofn = file.getOriginalFilename();
        if(StringUtils.isBlank(ofn)){
            throw new DfsException("文件名称不能为空");
        }
        try {
            String path = StringUtils.isBlank(dfsProperties.getTmpPath()) ? PathUtils.getPath() : dfsProperties.getTmpPath();
            File localTempFile = new File(path, ofn);
            File p = localTempFile.getParentFile();
            if(!p.exists()){
                if(!p.mkdirs()){
                    throw new DfsException("创建临时文件保存目录[" + p.getAbsolutePath() + "]失败");
                }
            }
            file.transferTo(localTempFile);
            return localTempFile;
        } catch (IOException e) {
            throw new DfsException("存储文件到本地失败",e);
        }
    }

    public Long save(@NotNull Long userId,@NotNull String fileName, @NotNull String path, @NotNull String digest) {
        Class<?> cls = ParameterTypeUtils.getSuperClassGenericType(getClass(),0);
        UserFile entity = null;
        try {
            entity = (UserFile) cls.getConstructor().newInstance();
            entity.setDigest(digest);
            entity.setFileName(fileName);
            entity.setPath(path);
            entity.setUserId(userId);
            insertSelective(entity);
            return entity.getId();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new SystemException("创建实体对象失败",e);
        }
    }
    public DfsResult uploadFile(String digest, File file) {
        String path = webDfsService.storePath(digest,file);
        // 上传到分布式文件系统后
        return webDfsService.uploadFile(path,file);
    }
    public Long uploadFile(File localTempFile,Long Id) {
        String digest = Sha1Util.sha1(localTempFile);
        UserFile entity = mapper.selectDigest(digest);
        if(entity == null){
            DfsResult result = uploadFile(digest, localTempFile);
            if(!result.success()){
                throw new DfsException(result.getMessage());
            }
            return save(Id,localTempFile.getName(),result.getDescriptor().path(),digest);
        }else{
            if(!webDfsService.exist(webDfsService.dfsFile(entity.getPath()))){
                //文件系统中不存在，那再上次一次文件
                String storePath = StringUtils.isBlank(entity.getPath())?webDfsService.storePath(digest, localTempFile):entity.getPath();
                DfsResult result = webDfsService.uploadFile(storePath, localTempFile);
                if(!result.success()){
                    throw new DfsException(result.getMessage());
                }
                update(entity.getId(),"path",result.getDescriptor().path());
                update(entity.getId(),"fileName", localTempFile.getName());
                update(entity.getId(),"userId", Id);
            }
            return entity.getId();
        }
    }
    public Long uploadFile(MultipartFile file,Long Id) {
        File localTempFile = transToLocalFile(file);
        try{
            return uploadFile(localTempFile,Id);
        }finally {
            localTempFile.delete();
        }
    }

    public void downloadFile(@NotNull Token token, @NotNull HttpServletResponse response, @NotNull Long id) {
       UserVo uservo=movieServiceInvoker.userInfo(id);
        if(uservo!=null) {
            Long userFileId= mapper.selectUserFileId(id);
            ErrorCode.RECORD_NOT_EXIST.assertNotNull(userFileId);
            UserFile userfile=mapper.selectUserFile(userFileId);
            downloadFile(response,userfile.getId(),userfile.getFileName());
        }

    }

    @Override
    public void downloadFile(HttpServletResponse response, Long id, @NotNull String FileName) {
        UserFile ucf=select(id);
        ErrorCode.COVER_NOT_EXIST.assertNotNull(ucf,FileName);
        DfsDescriptor descriptor = webDfsService.dfsFile(ucf.getPath());
        ErrorCode.COVER_FILE_NOT_FOUND.assertTrue(webDfsService.exist(descriptor),FileName,descriptor.path());
        webDfsService.downloadFile(response,descriptor, ucf.getFileName());
    }


}
